package tt.dz.service.imp.sys;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSON;

import tt.dz.dao.ext.charger.OmsChargerBespeakBillRecordDao;
import tt.dz.dao.ext.charger.OmsChargerChargeBillRecordDao;
import tt.dz.dao.ext.charger.OmsChargerDao;
import tt.dz.dao.ext.charger.OmsChargerOfflineWhitelistDao;
import tt.dz.dao.ext.common.OmsSplitratioSchemeDao;
import tt.dz.dao.ext.station.OmsStationDao;
import tt.dz.entity.base.JsonCommon;
import tt.dz.entity.charger.OmsCharger;
import tt.dz.entity.charger.OmsChargerBespeakBillRecord;
import tt.dz.entity.charger.OmsChargerChargeBillRecord;
import tt.dz.entity.charger.OmsChargerErrorRecord;
import tt.dz.entity.charger.OmsChargerOfflineWhitelist;
import tt.dz.entity.exception.BizException;
import tt.dz.entity.station.OmsStation;
import tt.dz.service.charger.OmsChargerErrorRecordService;
import tt.dz.service.imp.middleware.PriceService;
import tt.dz.tcp.rpc.as.SystemAppServerRpcClient;
import tt.dz.tcp.rpc.as.client.entity.AppOrderNotifyParam;
import tt.dz.tcp.rpc.os.OrderRpcClient;
import tt.dz.util.OmsConstant;
import tt.dz.util.OrderConstant;
import tt.dz.util.StringUtil;
import tt.dz.util.serialGenerater;
import tt.dz.vo.os.OrderBaseData;
import tt.dz.vo.os.RetVO;
import tt.dz.vo.os.RetVO.CreatedOrderVO;

public abstract class AbstractCardBillProcess implements UploadBillProcess
{
	private Log log = LogFactory.getLog(AbstractCardBillProcess.class);

	@Resource
	OmsSplitratioSchemeDao omsSplitratioSchemeDao;

	@Resource
	OmsChargerDao omsChargerDao;
	
	@Resource
	OmsStationDao omsStationDao;

	@Resource
	OmsChargerChargeBillRecordDao omsChargerChargeBillRecordDao;

	@Resource
	OmsChargerOfflineWhitelistDao omsChargerOfflineWhitelistDao;

	@Resource
	SystemAppServerRpcClient systemAppServerRpcClient;

	@Resource
	OmsChargerBespeakBillRecordDao omsChargerBespeakBillRecordDao;

	@Resource
	OrderRpcClient orderRpcClient;

	@Resource
	PriceService priceService;

	@Resource
	OmsChargerErrorRecordService omsChargerErrorRecordService;

	protected abstract void setCardType(Map<String, String> map);

	protected abstract boolean hasOnlineWhiteList();

	protected abstract boolean useChargersBill(boolean allowChargerGenerateBill);

	protected abstract OrderConstant.BizSystemCode getBillSource();//Fixme luoyp: It is wrong to use the card number to retrieve the source, have to let the consumer to pass the source id

	//维度1：账单上传时，通过判断本次充电是否是由预约转为充电，来确定本次订单生成时是否加入预约费用。
	//维度2：关于白名单：1：只有现金卡和APP卡才有可能是白名单，而现金卡一律以桩上传数据为准，由桩自己去判断是否是白名单；2：APP卡的话，一律以ＯＭＳ为准，线上判断是否白名单。
	//维度3:1.X和2.0的协议中，计算预约费：是同样的算法,每个费率区间内的时间*费率，然后累加；计算电费：1.X是依据充电总电量按照充电跨的费率区间来折算电量*费率，然后累加；2.X是按照每段精确的电量*费率，然后累加；
	//     计算服务费:1.X是一个桩对应一个固定的服务费率，费率*电量=服务费；2.0的计算方式与电费类似。这里也就要求设置服务费率时必须与电费费率的几个时间区间保持一致。
	//维度4：目前拟注册时把默认的三种费率方案号赋给电桩。
	@Override
	public Map<String, String> ProcessBill(Map<String, String> map) throws Exception
	{
		setCardType(map);
		log.info(map);
		String chargerId = map.get("chargerId");
		String cardType = map.get("cardType");
		String portNo = map.get("portNo");
		
		if(StringUtil.isBlank(cardType)){
			log.info("cardType null ");
			throw new BizException("cardType null ");
		}
		log.info(chargerId);

		OmsCharger charger = omsChargerDao.findOneExample(new OmsCharger(chargerId), null, null);
		if (charger == null) throw new BizException("Charger not found");
		OmsStation omsStaionQuery = new OmsStation(charger.getStation_id());
		OmsStation omsStaion = omsStationDao.findRecordByPK(omsStaionQuery);
		
		
		String start_time_msg = map.get("start_time");
		String end_time_msg = map.get("end_time");
		Date start_time_msg_date =null,end_time_msg_date = null;
		start_time_msg_date =StringUtil.StrToDate(start_time_msg);
		end_time_msg_date = StringUtil.StrToDate(end_time_msg);
		
		String userCard = map.get("user_pay_card");

		BigDecimal start_em = (new BigDecimal(map.get("start_em"))).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP); //*充电前电表读数 BIN码 4 系数为0.01 低字节在前，高字节在后，实际值X100上送
		BigDecimal end_em = (new BigDecimal(map.get("end_em"))).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);//(map.get("end_em")); //*充电后电表读数 BIN码 4 系数为0.01 低字节在前，高字节在后，实际值X100上送
		BigDecimal this_reading = (new BigDecimal(map.get("this_reading"))).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);//(map.get("this_reading"));//*本次充电电量  与上类似
		BigDecimal offline_balance_end = (new BigDecimal(map.get("offline_balance_end"))).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);//充电后卡余额  与上类似

		BigDecimal charging_fee = (new BigDecimal(map.get("charging_fee"))).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);//*本次充电金额  与上类似
		BigDecimal service_fee = (new BigDecimal(map.get("service_fee"))).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);//

		log.info("charging_fee = "+charging_fee);
		log.info("service_fee = "+service_fee);

		String oms_msg_charge_jrnl = map.get("oms_msg_charge_jrnl");//之前充电的流水号
		String vin = map.get("vin");//车辆识别码

		OmsChargerChargeBillRecord chargingBill = omsChargerChargeBillRecordDao.findOneExample(new OmsChargerChargeBillRecord(oms_msg_charge_jrnl,null), "create_time", "desc");
		if (chargingBill == null)//pengyu add 线下刷卡账单只记录，不同步给OS pengyu modify ht需要线下的记录同步给OS  线下的账单中简单都认为是A口。chargingBill.setPort_no(1);
		{
			log.info("chargingBill == null");
//			throw new BizException("Bill record not found");
			chargingBill = new OmsChargerChargeBillRecord();
//			OmsChargerChargeBillRecord bill = new OmsChargerChargeBillRecord();
			String serialNo = serialGenerater.generateSerialNo();

			String charge_jrnl = chargerId + "01" + serialNo;

//			chargingBill.setCharge_jrnl(charge_jrnl);
//			chargingBill.setCharger_id(chargerId);
//			chargingBill.setStation_id(charger.getStation_id());
//			chargingBill.setPort_no(1);
//			chargingBill.setUser_pay_card(userCard);
//			chargingBill.setStatus(OmsConstant.ChargingBillStatus.BillGenerated);
//			chargingBill.setValid_flag(1);
//			chargingBill.setOrder_no("offline");
//
//
//			chargingBill.setStart_em(start_em.toString());
//			chargingBill.setEnd_em(end_em.toString());
//			chargingBill.setThis_reading(this_reading.toString());
//			chargingBill.setThis_amount_before(charging_fee.floatValue());
//			chargingBill.setThis_amount(charging_fee.floatValue());
//
//			chargingBill.setChar_bill_before(service_fee.floatValue());
//			chargingBill.setChar_bill(service_fee.floatValue());
//
//			chargingBill.setOffline_balance_end(String.valueOf(offline_balance_end));
//			chargingBill.setVIN(vin);
			
			//优化过了。之后这种情况的，结束充电流水号为：只有刷卡记录 20180411 
			chargingBill = new OmsChargerChargeBillRecord(charge_jrnl, chargerId, userCard, service_fee.floatValue(), service_fee.floatValue(), charger.getStation_id(),
					start_em.toString(), end_em.toString(), this_reading.toString(), charging_fee.floatValue(), charging_fee.floatValue(), String.valueOf(offline_balance_end),
					OmsConstant.ChargingBillStatus.BillGenerated, 1, 1, vin, "offline");
			chargingBill.setMsg_charge_jrnl(oms_msg_charge_jrnl);
			chargingBill.setStart_time(start_time_msg_date);
			chargingBill.setEnd_time(end_time_msg_date);
			chargingBill.setCreate_time(new Date());
			chargingBill.setMsg_charge_end_jrnl("只有刷卡记录");
			omsChargerChargeBillRecordDao.save(chargingBill);
//			return map;
		}
		else if (StringUtils.isNotEmpty(chargingBill.getOrder_no())) // 数据库中已经存在订单,记录日志信息,不做异常处理
		{
			log.info(chargingBill.getCharge_jrnl() + "result -> Order have been generated for this bill, existing order No.: ");
			throw new BizException("Order have been generated for this bill, existing order No.: " + chargingBill.getOrder_no());
		}



		if(StringUtil.isBlank(start_time_msg) || StringUtil.isBlank(end_time_msg)){
			log.info("start_time or end_time is null:upBill oms_msg_charge_jrnl = " +oms_msg_charge_jrnl);
			throw new BizException("start_time or end_time is null:upBill oms_msg_charge_jrnl = " +oms_msg_charge_jrnl);
		}
		//直接做覆盖的结果就是，如果最后桩上传的充电

		if(chargingBill.getStart_time() ==null){
			chargingBill.setStart_time(start_time_msg_date);
		}
		if(chargingBill.getEnd_time() ==null){
			chargingBill.setEnd_time(end_time_msg_date);
		}
		
		if (this_reading.compareTo(new BigDecimal(OrderConstant.UPLOAD_BILL_CHARGE_POWER_MAX)) > 0)
		{ // 入库oms_charger_error_record[故障记录表]
			log.error("Power exception!" + this_reading);
//			OmsChargerErrorRecord record = new OmsChargerErrorRecord();
//			record.setCharger_id(chargerId);
//			record.setError_msg("Current power fee: " + this_reading);
//			record.setError_code("error");
//			record.setStatus(0); // 0:未处理,1:已处理
//			record.setValid_flag(1);
//			record.setCreate_oper_id("000");
//			record.setCreate_time(new Date());
			OmsChargerErrorRecord record = new OmsChargerErrorRecord(chargerId, "error", "Current power fee: " + this_reading, "000");
			omsChargerErrorRecordService.add(record);
			throw new BizException("Power exception " + this_reading);
		}

		log.info("chargingBill.getCharge_jrnl() = "+chargingBill.getCharge_jrnl());

		List<PaymentDetail> chargingFeeDetails = new ArrayList<>();
		List<PaymentDetail> serviceFeeDetails = new ArrayList<>();



		BigDecimal reservation_fee = null;
		List<PaymentDetail> reservationFeeDetails = new ArrayList<>();
		//pengyu modify 20160515
		OmsChargerBespeakBillRecord reservation = null;
		if (chargingBill.getBespeak_jrnl() != null)
		{
			OmsChargerBespeakBillRecord reservation_query = new OmsChargerBespeakBillRecord();
			reservation_query.setBespeak_jrnl(chargingBill.getBespeak_jrnl());
			reservation = omsChargerBespeakBillRecordDao.findOneExample(reservation_query, null, null);
			if (reservation != null)
			{
				reservation_fee = priceService.computeFee(charger.getRate_schema_bespeak_fee(), reservation.getStart_time(), reservation.getActual_end_time(), reservationFeeDetails);
				log.info(reservation_fee);
				log.info(reservationFeeDetails);
			}
		}

		log.debug(charger.getIs_allow_generate_fee());

		//如果不使用桩生成的费用, 那么费用由服务器自己计算
		if (!useChargersBill(charger.getIs_allow_generate_fee() == 1))
		{ // 是否允许桩生成费用,0:不允许 1:允许
			log.info("compute in server side");
			String protocol_version = map.get("protocol_version");
			float[] float_chargingAmounts = null;
			String listCharingAmount = map.get("listCharingAmount");
			if ("0201".equals(protocol_version))
			{
				if (StringUtils.isNotEmpty(listCharingAmount))
				{
					String[] chargingAmounts = listCharingAmount.split(",");
					if (chargingAmounts != null && chargingAmounts.length > 0)
					{
						float_chargingAmounts = new float[chargingAmounts.length];
						for (int i = 0; i < chargingAmounts.length; i++)
						{
							float_chargingAmounts[i] = (new BigDecimal(chargingAmounts[i])).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).floatValue();
						}
					}
				}
				if (float_chargingAmounts == null)
				{
					//				throw new BizException("Invalid charging amounts uploaded by charger");
					charging_fee = BigDecimal.ZERO;
					log.error("Number of charging amount is wrong , default the charging fee to 0");//Fixme luoyp, throw an exception if the number of amount is wrong in the future development
				}
				else
					charging_fee = priceService.computeChargingFee(charger.getRate_schema_charge_fee(), chargingBill.getStart_time(), chargingBill.getEnd_time(), float_chargingAmounts, chargingFeeDetails);
			}
			else
			{
				charging_fee = priceService.computeChargingFeeRoughly(charger.getRate_schema_charge_fee(), chargingBill.getStart_time(), chargingBill.getEnd_time(), this_reading.floatValue());
				PaymentDetail detail = new PaymentDetail(charging_fee.floatValue(), charging_fee.floatValue() / this_reading.floatValue(), this_reading.floatValue(), chargingBill.getStart_time(),
						chargingBill.getEnd_time(), OmsConstant.PaymentMode.ByTime);
				chargingFeeDetails.add(detail);
			}

			service_fee = priceService.computeFee(charger.getRate_schema_service_fee(), chargingBill.getStart_time(), chargingBill.getEnd_time(), serviceFeeDetails);
		}
		else if (this_reading.floatValue() != 0 && chargingBill.getStart_time() != null && chargingBill.getEnd_time() != null)
		{
			PaymentDetail detail = new PaymentDetail(charging_fee.floatValue(), charging_fee.floatValue() / this_reading.floatValue(), this_reading.floatValue(), chargingBill.getStart_time(), chargingBill.getEnd_time(),
					OmsConstant.PaymentMode.ByTime);
			chargingFeeDetails.add(detail);

			long num = (chargingBill.getEnd_time().getTime() - chargingBill.getStart_time().getTime()) / 60000;
			PaymentDetail detail2 = new PaymentDetail(service_fee.floatValue(), service_fee.floatValue() / num, num, chargingBill.getStart_time(), chargingBill.getEnd_time(), OmsConstant.PaymentMode.ByTime);
			serviceFeeDetails.add(detail2);
		}
		log.info(charging_fee);
		log.info(service_fee);

		//该卡是否存在白名单免费
		if (hasOnlineWhiteList())
		{
			log.info("hasOnlineWhiteList begin");
			//查询卡号是不是在白名单里面。
			OmsChargerOfflineWhitelist whitelist_query = new OmsChargerOfflineWhitelist();
			whitelist_query.setCharger_id(chargerId);
			whitelist_query.setUser_pay_card(userCard);
			OmsChargerOfflineWhitelist whitelist = omsChargerOfflineWhitelistDao.findOneExample(whitelist_query, null, null);
			if (whitelist != null)
			{
				service_fee = BigDecimal.ZERO;
				charging_fee = BigDecimal.ZERO;
				reservation_fee = BigDecimal.ZERO;
			}
			log.info("hasOnlineWhiteList end");
		}

		List<OrderBaseData> list_orderBaseDatas = new ArrayList<>();

		String is_paid = map.get("offline_is_pay");
		log.info("create an order via order server");
		log.info("getBillSource().value() = "+getBillSource().value());
		OrderBaseData orderBaseData_ServiceFee = new OrderBaseData();
		orderBaseData_ServiceFee.setAppId(getBillSource().value());
//		orderBaseData_ServiceFee.setBuyNum(new BigDecimal((chargingBill.getEnd_time().getTime() - chargingBill.getStart_time().getTime()) / (1000 * 60)));
		orderBaseData_ServiceFee.setBuyNum(this_reading);//充电的服务费 和 电费 对应的单位都是电量，所以都是 this_reading20180411
		orderBaseData_ServiceFee.setCardNo(userCard);
		orderBaseData_ServiceFee.setCardType(cardType);
		orderBaseData_ServiceFee.setStartTime(chargingBill.getStart_time());
		orderBaseData_ServiceFee.setEndTime(chargingBill.getEnd_time());
		orderBaseData_ServiceFee.setEquipmentNo(chargerId);
		if(omsStaion!=null){
			orderBaseData_ServiceFee.setPlantName(omsStaion.getStation_name());
		}
		orderBaseData_ServiceFee.setPlantId(charger.getStation_id());
		orderBaseData_ServiceFee.setServiceNo(OrderConstant.OrderServiceEnum.ChargeService.value());
		orderBaseData_ServiceFee.setServiceProviderCode(charger.getOper_merchant_id());
//		orderBaseData_ServiceFee.setAuxEquipmentNo(String.valueOf(charger.getPort_no()));
		orderBaseData_ServiceFee.setAuxEquipmentNo(StringUtil.isBlank(portNo)?"1":portNo);
		orderBaseData_ServiceFee.setTotalPrice(service_fee);
		orderBaseData_ServiceFee.setPayStatus(0);
		orderBaseData_ServiceFee.setMessage(JSON.toJSONString(serviceFeeDetails));
//		if ("1".equals(is_paid))
//		{
//			orderBaseData_ServiceFee.setPayStatus(7);
//			orderBaseData_ServiceFee.setPayType(6);
//		}
		log.info("begin to fee ratio");
		//账单分成
		StringBuffer sql = new StringBuffer();
		sql.append(" SELECT u.charger_id, u.service_no, group_concat(u.entity) entity_con, GROUP_CONCAT(u.ratios) ratio_con ");
		sql.append(" FROM ( ");
		sql.append(" 	SELECT CASE CONCAT (s.entity_id, s.entity_type) ");
		sql.append(" 			WHEN '*1' ");
		sql.append(" 				THEN c.oper_merchant_id ");
		sql.append(" 			WHEN '*4' ");
		sql.append(" 				THEN c.entity_id ");
		sql.append(" 			ELSE s.entity_id ");
		sql.append(" 			END entity,  ");
		sql.append(" 			s.entity_id, s.entity_type, s.ratios, s.service_no, c.oper_merchant_id, c.entity_id partner_id, c.charger_id ");
		sql.append(" 	FROM oms_charger c ");
		sql.append(" 	INNER JOIN oms_service_splitratio m ON c.charger_id = m.charger_id ");
		sql.append(" 	INNER JOIN oms_splitratio_scheme s ON s.service_no = m.service_no AND s.scheme_no = m.scheme_no ");
		sql.append(" 	WHERE c.valid_flag = 1 AND m.valid_flag = 1 AND s.valid_flag = 1 AND c.charger_id = ? ");
		sql.append(" 	) u ");
		sql.append(" GROUP BY u.charger_id, u.service_no ");
		List<Map<String, Object>> list_splitinfo = omsSplitratioSchemeDao.findDataBySql(sql.toString(), chargerId);

		for (Map<String, Object> m : list_splitinfo)
		{
			if (OrderConstant.OrderServiceEnum.ChargeService.value().equals(m.get("service_no")))
			{
				OrderBaseData.DivideInfo divideInfo = new OrderBaseData.DivideInfo();
				divideInfo.setMerchantCodes(m.get("entity_con").toString());
				divideInfo.setRatios(m.get("ratio_con").toString());
				orderBaseData_ServiceFee.setDivideInfo(divideInfo);
				break;
			}
		}

		OrderBaseData orderBaseData_Chargingfee = new OrderBaseData();
		orderBaseData_Chargingfee.setAppId(getBillSource().value());
		orderBaseData_Chargingfee.setBuyNum(this_reading);
		orderBaseData_Chargingfee.setCardNo(userCard);
		orderBaseData_Chargingfee.setCardType(cardType);
		orderBaseData_Chargingfee.setStartTime(chargingBill.getStart_time());
		orderBaseData_Chargingfee.setEndTime(chargingBill.getEnd_time());
		orderBaseData_Chargingfee.setEquipmentNo(chargerId);
		if(omsStaion!=null){
			orderBaseData_Chargingfee.setPlantName(omsStaion.getStation_name());
		}
		orderBaseData_Chargingfee.setPlantId(charger.getStation_id());
		orderBaseData_Chargingfee.setServiceNo(OrderConstant.OrderServiceEnum.CollectingElectricityFee.value());
		orderBaseData_Chargingfee.setServiceProviderCode(charger.getOper_merchant_id());
//		orderBaseData_Chargingfee.setAuxEquipmentNo(String.valueOf(charger.getPort_no()));
		orderBaseData_Chargingfee.setAuxEquipmentNo(StringUtil.isBlank(portNo)?"1":portNo);
		orderBaseData_Chargingfee.setTotalPrice(charging_fee);
		orderBaseData_Chargingfee.setPayStatus(0);
		orderBaseData_Chargingfee.setMessage(JSON.toJSONString(chargingFeeDetails));
		
		switch(cardType){
		case "08"://线上卡
				orderBaseData_Chargingfee.setPayStatus(0);
				orderBaseData_ServiceFee.setPayStatus(6);
//				orderBaseData_Chargingfee.setPayType(6);
			break;
		case "06"://线下卡
			if ("1".equals(is_paid)){
				orderBaseData_Chargingfee.setPayStatus(7);
				orderBaseData_Chargingfee.setPayType(6);
				orderBaseData_ServiceFee.setPayStatus(7);
				orderBaseData_ServiceFee.setPayType(6);
			}else if("0".equals(is_paid)){
				orderBaseData_Chargingfee.setPayStatus(0);
				orderBaseData_Chargingfee.setPayType(6);
				orderBaseData_ServiceFee.setPayStatus(0);
				orderBaseData_ServiceFee.setPayType(6);
			} 
			break;
		default:
			break;
		}
		
		

		if (reservation != null)
		{
			OrderBaseData orderBaseData_ReservationFee = new OrderBaseData();
			orderBaseData_ReservationFee.setCardNo(userCard);
			orderBaseData_ReservationFee.setCardType(cardType);
			orderBaseData_ReservationFee.setPayerBalance("0");
			orderBaseData_ReservationFee.setAppId(getBillSource().value());
			orderBaseData_ReservationFee.setServiceNo(OrderConstant.OrderServiceEnum.Reservation.value());
			orderBaseData_ReservationFee.setServiceProviderCode(charger.getOper_merchant_id());
			if(omsStaion!=null){
				orderBaseData_ReservationFee.setPlantName(omsStaion.getStation_name());
			}
			orderBaseData_ReservationFee.setPlantId(charger.getStation_id());
			orderBaseData_ReservationFee.setEquipmentNo(chargerId);
			orderBaseData_ReservationFee.setAuxEquipmentNo(String.valueOf(charger.getPort_no()));
			orderBaseData_ReservationFee.setTotalPrice(reservation_fee);
			orderBaseData_ReservationFee.setBuyNum(new BigDecimal((reservation.getActual_end_time().getTime() - reservation.getStart_time().getTime()) / (1000 * 60)));
			orderBaseData_ReservationFee.setStartTime(reservation.getStart_time());
			orderBaseData_ReservationFee.setEndTime(reservation.getActual_end_time());
			orderBaseData_ReservationFee.setPayStatus(0);
			orderBaseData_ReservationFee.setMessage(JSON.toJSONString(reservationFeeDetails));
			if ("1".equals(is_paid))
			{
				orderBaseData_ReservationFee.setPayStatus(7);
				orderBaseData_ReservationFee.setPayType(6);
			}
			if (reservation_fee.compareTo(new BigDecimal(OrderConstant.UPLOAD_BILL_CHARGE_BESPEAK_MAX)) > 0)
			{ // 入库oms_charger_error_record[故障记录表]
				log.error("Bespeak fee exception!");
				OmsChargerErrorRecord record = new OmsChargerErrorRecord();
				record.setCharger_id(chargerId);
				record.setError_code("error");
				record.setError_msg("Bespeak fee exception!");
				record.setStatus(0); // 0:未处理,1:已处理
				record.setValid_flag(1);
				record.setCreate_oper_id("000");
				record.setCreate_time(new Date());
				omsChargerErrorRecordService.add(record);
				throw new BizException("Bespeak fee exception " + reservation_fee);
			}
			list_orderBaseDatas.add(orderBaseData_ReservationFee);
		}

		if (orderBaseData_ServiceFee.getTotalPrice().compareTo(new BigDecimal(OrderConstant.UPLOAD_BILL_CHARGE_SERVICE_MAX)) > 0)
		{ // 入库oms_charger_error_record[故障记录表]
			log.error("Service fee exception!");
			OmsChargerErrorRecord record = new OmsChargerErrorRecord();
			record.setCharger_id(chargerId);
			record.setError_code("error");
			record.setError_msg("Service fee exception!");
			record.setStatus(0); // 0:未处理,1:已处理
			record.setValid_flag(1);
			record.setCreate_oper_id("000");
			record.setCreate_time(new Date());
			omsChargerErrorRecordService.add(record);
			throw new BizException("Service fee exception " + service_fee);
		}

		if (orderBaseData_Chargingfee.getTotalPrice().compareTo(new BigDecimal(OrderConstant.UPLOAD_BILL_CHARGE_CHARGING_MAX)) > 0)
		{ // 入库oms_charger_error_record[故障记录表]
			log.error("charging fee exception!");
			OmsChargerErrorRecord record = new OmsChargerErrorRecord();
			record.setCharger_id(chargerId);
			record.setError_code("error");
			record.setError_msg("charging fee exception!");
			record.setStatus(0); // 0:未处理,1:已处理
			record.setValid_flag(1);
			record.setCreate_oper_id("000");
			record.setCreate_time(new Date());
			omsChargerErrorRecordService.add(record);
			throw new BizException("charging fee exception" + charging_fee);
		}

		list_orderBaseDatas.add(orderBaseData_ServiceFee);
		list_orderBaseDatas.add(orderBaseData_Chargingfee);

		for (int i = 0; i < list_orderBaseDatas.size(); i++)
		{
			log.info("aaaaaa list_orderBaseDatas = " + list_orderBaseDatas.get(i).toString());
		}

		log.info("send to AbstractCardBillProcess ProcessBill orderRpcClient.createOrder start curTime = " + new Date().getTime());
		RetVO retVO = orderRpcClient.createOrder(list_orderBaseDatas);
		log.info("send to ProcessBill orderRpcClient.createOrder end curTime = " + new Date().getTime());
		if (retVO == null || !retVO.getRetCode().equals(retVO.SuccessCode))
			throw new BizException("error occurred when creating order by calling order server");

		log.info(retVO);

		String bizData = (String) retVO.getBizData();
		CreatedOrderVO createdOrderVO = JSON.parseObject(bizData, CreatedOrderVO.class);
		String order_no = createdOrderVO.getOrderNo();
		log.info(order_no);

		float charging_fee_discount = 0;
		float service_fee_discount = 0;
		float reservation_fee_discount = 0;
		for (RetVO.ServicePriceVO vo : createdOrderVO.getOrderItemVOList())
		{
			if (OrderConstant.OrderServiceEnum.Reservation.value().equals(vo.getServiceNo()))
			{
				reservation_fee_discount = vo.getRealPrice().floatValue();
			}
			else if (OrderConstant.OrderServiceEnum.ChargeService.value().equals(vo.getServiceNo()))
			{
				service_fee_discount = vo.getRealPrice().floatValue();
			}
			else if (OrderConstant.OrderServiceEnum.CollectingElectricityFee.value().equals(vo.getServiceNo()))
			{
				charging_fee_discount = vo.getRealPrice().floatValue();
			}
		}
//		String onLineCardType = CardType.ONLINE_CARD.value();
		//pengyu modify 20170724
		switch(cardType){
		case "08"://线上卡才通知AS
			log.info("Notify AS on order generated curTime = " + new Date().getTime());
			AppOrderNotifyParam appOrderNotifyParam = new AppOrderNotifyParam();
			appOrderNotifyParam.setUserCard(userCard);
			appOrderNotifyParam.setOrderNo(order_no);
			appOrderNotifyParam.setMoney(createdOrderVO.getTotalFee().toString());
			log.info("send to ProcessBill systemAppServerRpcClient.orderNotify start curTime = " + new Date().getTime());
			JsonCommon<String> result = systemAppServerRpcClient.orderNotify(appOrderNotifyParam);
			log.info("send to ProcessBill systemAppServerRpcClient.orderNotify end curTime = " + new Date().getTime());
			log.info(result);
			break;
		default:
			break;
		}

		chargingBill.setOrder_no(order_no);
		chargingBill.setStart_em(start_em.toString());
		chargingBill.setEnd_em(end_em.toString());
		chargingBill.setThis_reading(this_reading.toString());
		chargingBill.setThis_amount_before(charging_fee.floatValue());
		chargingBill.setThis_amount(charging_fee_discount);

		chargingBill.setChar_bill_before(service_fee.floatValue());
		chargingBill.setChar_bill(service_fee_discount);

		chargingBill.setOffline_balance_end(String.valueOf(offline_balance_end));
		chargingBill.setValid_flag(1);
		chargingBill.setVIN(vin);
		chargingBill.setUser_pay_card(userCard);
		chargingBill.setStatus(OmsConstant.ChargingBillStatus.BillGenerated);

		omsChargerChargeBillRecordDao.updateObject(chargingBill);
		log.info("update chargingBill = " + reservation);

		if (reservation != null)
		{
			reservation.setBespeak_deal_before(reservation_fee.floatValue());
			reservation.setBespeak_deal_charge(reservation_fee_discount);
			reservation.setOrder_no(order_no);
			reservation.setIs_done(1);
			omsChargerBespeakBillRecordDao.updateObject(reservation);
			log.info("update Object reservation = " + reservation);
		}

		return map;
	}

}
